---
title: "Functions and Closures in Swift"
description: "Learn how to define and use functions and closures in Swift, with direct comparisons to JavaScript."
---

## 1. Introduction

Functions and closures are fundamental building blocks in both JavaScript and Swift. While JavaScript treats functions as first-class citizens, Swift brings additional safety, clarity, and expressive power, especially with its type system and closure syntax.

**Key Learning Objectives:**
- Understand function declaration and usage in Swift
- Compare parameter handling and return values
- Learn closure syntax and usage
- Explore higher-order functions and functional programming patterns

## 2. Function Declaration and Parameters

### 2.1 Basic Function Declaration

<UniversalEditor title="Function Declaration Comparison" compare={true}>
```javascript !! js
// JavaScript function declaration
function greet(name) {
    return `Hello, ${name}!`;
}

// Arrow function
const greetArrow = (name) => `Hello, ${name}!`;

console.log(greet("Alice"));
console.log(greetArrow("Bob"));
```

```swift !! swift
// Swift function declaration
func greet(name: String) -> String {
    return "Hello, \(name)!"
}

print(greet(name: "Alice"))
```
</UniversalEditor>

### 2.2 Parameters and Return Values

Swift requires explicit parameter types and return types, making code safer and more predictable.

<UniversalEditor title="Parameters and Return Values" compare={true}>
```javascript !! js
// JavaScript - parameters and return values
function add(a, b) {
    return a + b;
}

function sayHello() {
    return "Hello!";
}

console.log(add(2, 3));
console.log(sayHello());
```

```swift !! swift
// Swift - parameters and return values
func add(a: Int, b: Int) -> Int {
    return a + b
}

func sayHello() -> String {
    return "Hello!"
}

print(add(a: 2, b: 3))
print(sayHello())
```
</UniversalEditor>

### 2.3 Default and Variadic Parameters

<UniversalEditor title="Default and Variadic Parameters" compare={true}>
```javascript !! js
// JavaScript default and rest parameters
function greet(name = "World") {
    return `Hello, ${name}!`;
}

function sum(...numbers) {
    return numbers.reduce((acc, n) => acc + n, 0);
}

console.log(greet());
console.log(sum(1, 2, 3, 4));
```

```swift !! swift
// Swift default and variadic parameters
func greet(name: String = "World") -> String {
    return "Hello, \(name)!"
}

func sum(_ numbers: Int...) -> Int {
    return numbers.reduce(0, +)
}

print(greet())
print(sum(1, 2, 3, 4))
```
</UniversalEditor>

## 3. Closures (Anonymous Functions)

### 3.1 Closure Syntax Basics

Closures in Swift are similar to JavaScript's anonymous functions (lambdas/arrow functions), but with more concise and flexible syntax.

<UniversalEditor title="Closure Syntax Comparison" compare={true}>
```javascript !! js
// JavaScript anonymous functions and arrow functions
const add = function(a, b) {
    return a + b;
};

const multiply = (a, b) => a * b;

console.log(add(2, 3));
console.log(multiply(4, 5));
```

```swift !! swift
// Swift closure expressions
let add = { (a: Int, b: Int) -> Int in
    return a + b
}

let multiply: (Int, Int) -> Int = { a, b in a * b }

print(add(2, 3))
print(multiply(4, 5))
```
</UniversalEditor>

### 3.2 Closure Shorthand Syntax

Swift provides several ways to write closures more concisely.

<UniversalEditor title="Closure Shorthand Syntax" compare={true}>
```javascript !! js
// JavaScript arrow function shorthand
const numbers = [1, 2, 3, 4, 5];

// Full arrow function
const doubled = numbers.map((num) => {
    return num * 2;
});

// Shorthand arrow function
const tripled = numbers.map(num => num * 3);

// Even shorter with implicit return
const squared = numbers.map(num => num ** 2);

console.log(doubled);
console.log(tripled);
console.log(squared);
```

```swift !! swift
// Swift closure shorthand syntax
let numbers = [1, 2, 3, 4, 5]

// Full closure syntax
let doubled = numbers.map({ (num: Int) -> Int in
    return num * 2
})

// Type inference
let tripled = numbers.map({ num in
    return num * 3
})

// Shorthand argument names
let squared = numbers.map({ $0 * $0 })

// Trailing closure syntax
let filtered = numbers.filter { $0 > 2 }

print(doubled)
print(tripled)
print(squared)
print(filtered)
```
</UniversalEditor>

## 4. Higher-Order Functions

### 4.1 Map, Filter, Reduce

Swift's collection methods are similar to JavaScript's array methods, but with stronger type safety.

<UniversalEditor title="Higher-Order Functions" compare={true}>
```javascript !! js
// JavaScript array methods
const numbers = [1, 2, 3, 4, 5, 6];

// Map
const doubled = numbers.map(num => num * 2);

// Filter
const evens = numbers.filter(num => num % 2 === 0);

// Reduce
const sum = numbers.reduce((acc, num) => acc + num, 0);

// Chaining
const result = numbers
    .filter(num => num > 2)
    .map(num => num * 2)
    .reduce((acc, num) => acc + num, 0);

console.log(doubled);  // [2, 4, 6, 8, 10, 12]
console.log(evens);    // [2, 4, 6]
console.log(sum);      // 21
console.log(result);   // 30
```

```swift !! swift
// Swift collection methods
let numbers = [1, 2, 3, 4, 5, 6]

// Map
let doubled = numbers.map { $0 * 2 }

// Filter
let evens = numbers.filter { $0 % 2 == 0 }

// Reduce
let sum = numbers.reduce(0, +)

// Chaining
let result = numbers
    .filter { $0 > 2 }
    .map { $0 * 2 }
    .reduce(0, +)

print(doubled)  // [2, 4, 6, 8, 10, 12]
print(evens)    // [2, 4, 6]
print(sum)      // 21
print(result)   // 30
```
</UniversalEditor>

### 4.2 Custom Higher-Order Functions

<UniversalEditor title="Custom Higher-Order Functions" compare={true}>
```javascript !! js
// JavaScript custom higher-order functions
function forEach(array, callback) {
    for (let i = 0; i < array.length; i++) {
        callback(array[i], i, array);
    }
}

function find(array, predicate) {
    for (let item of array) {
        if (predicate(item)) {
            return item;
        }
    }
    return undefined;
}

const numbers = [1, 2, 3, 4, 5];

forEach(numbers, (num, index) => {
    console.log(`Number ${index}: ${num}`);
});

const firstEven = find(numbers, num => num % 2 === 0);
console.log(firstEven); // 2
```

```swift !! swift
// Swift custom higher-order functions
func forEach<T>(_ array: [T], _ callback: (T, Int) -> Void) {
    for (index, item) in array.enumerated() {
        callback(item, index)
    }
}

func find<T>(_ array: [T], _ predicate: (T) -> Bool) -> T? {
    for item in array {
        if predicate(item) {
            return item
        }
    }
    return nil
}

let numbers = [1, 2, 3, 4, 5]

forEach(numbers) { num, index in
    print("Number \(index): \(num)")
}

let firstEven = find(numbers) { $0 % 2 == 0 }
print(firstEven ?? "No even number found") // Optional(2)
```
</UniversalEditor>

## 5. Closure Capture and Memory Management

### 5.1 Closure Capture Lists

Swift's closure capture lists provide explicit control over how values are captured, unlike JavaScript's lexical scoping.

<UniversalEditor title="Closure Capture Lists" compare={true}>
```javascript !! js
// JavaScript closure capture (lexical scoping)
function createCounter() {
    let count = 0;
    
    return {
        increment: () => ++count,
        decrement: () => --count,
        getCount: () => count
    };
}

const counter = createCounter();
console.log(counter.getCount()); // 0
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1
```

```swift !! swift
// Swift closure capture lists
func createCounter() -> (increment: () -> Int, decrement: () -> Int, getCount: () -> Int) {
    var count = 0
    
    let increment = { [count] in
        count += 1
        return count
    }
    
    let decrement = { [count] in
        count -= 1
        return count
    }
    
    let getCount = { count }
    
    return (increment: increment, decrement: decrement, getCount: getCount)
}

let counter = createCounter()
print(counter.getCount()) // 0
print(counter.increment()) // 1
print(counter.increment()) // 2
print(counter.decrement()) // 1
```
</UniversalEditor>

### 5.2 Weak and Unowned References

Swift provides explicit control over reference cycles in closures.

<UniversalEditor title="Weak and Unowned References" compare={true}>
```javascript !! js
// JavaScript - no explicit weak references needed
class Person {
    constructor(name) {
        this.name = name;
        this.friends = [];
    }
    
    addFriend(friend) {
        this.friends.push(friend);
        friend.friends.push(this);
    }
    
    introduce() {
        console.log(`Hi, I'm ${this.name}`);
    }
}

const alice = new Person("Alice");
const bob = new Person("Bob");
alice.addFriend(bob);
```

```swift !! swift
// Swift - explicit weak references to prevent retain cycles
class Person {
    let name: String
    var friends: [Person] = []
    
    init(name: String) {
        self.name = name
    }
    
    func addFriend(_ friend: Person) {
        friends.append(friend)
        friend.friends.append(self)
    }
    
    func introduce() {
        print("Hi, I'm \(name)")
    }
    
    // Using weak reference to prevent retain cycle
    lazy var introduceClosure: () -> Void = { [weak self] in
        guard let self = self else { return }
        print("Hi, I'm \(self.name)")
    }
}

let alice = Person(name: "Alice")
let bob = Person(name: "Bob")
alice.addFriend(bob)
```
</UniversalEditor>

## 6. Functional Programming Patterns

### 6.1 Function Composition

<UniversalEditor title="Function Composition" compare={true}>
```javascript !! js
// JavaScript function composition
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

const addOne = x => x + 1;
const double = x => x * 2;
const square = x => x ** 2;

const composed = compose(square, double, addOne);
const piped = pipe(addOne, double, square);

console.log(composed(3)); // ((3 + 1) * 2) ^ 2 = 64
console.log(piped(3));    // ((3 + 1) * 2) ^ 2 = 64
```

```swift !! swift
// Swift function composition
func compose<T, U, V>(_ f: @escaping (U) -> V, _ g: @escaping (T) -> U) -> (T) -> V {
    return { f(g($0)) }
}

func pipe<T, U, V>(_ f: @escaping (T) -> U, _ g: @escaping (U) -> V) -> (T) -> V {
    return { g(f($0)) }
}

let addOne: (Int) -> Int = { $0 + 1 }
let double: (Int) -> Int = { $0 * 2 }
let square: (Int) -> Int = { $0 * $0 }

let composed = compose(square, compose(double, addOne))
let piped = pipe(addOne, pipe(double, square))

print(composed(3)) // ((3 + 1) * 2) ^ 2 = 64
print(piped(3))    // ((3 + 1) * 2) ^ 2 = 64
```
</UniversalEditor>

### 6.2 Currying and Partial Application

<UniversalEditor title="Currying and Partial Application" compare={true}>
```javascript !! js
// JavaScript currying
const add = (a) => (b) => a + b;
const addFive = add(5);

console.log(addFive(3)); // 8

// Partial application
const multiply = (a, b) => a * b;
const multiplyByTwo = multiply.bind(null, 2);

console.log(multiplyByTwo(4)); // 8
```

```swift !! swift
// Swift currying
func add(_ a: Int) -> (Int) -> Int {
    return { b in a + b }
}

let addFive = add(5)
print(addFive(3)) // 8

// Partial application using closures
func multiply(_ a: Int, _ b: Int) -> Int {
    return a * b
}

let multiplyByTwo: (Int) -> Int = { multiply(2, $0) }
print(multiplyByTwo(4)) // 8
```
</UniversalEditor>

## 7. Practice Exercises

### Exercise 1: Basic Functions and Closures

<UniversalEditor title="Exercise 1: Basic Functions and Closures" compare={true}>
```javascript !! js
// JavaScript exercise
function calculateArea(width, height) {
    return width * height;
}

const calculatePerimeter = (width, height) => 2 * (width + height);

function createGreeter(greeting) {
    return function(name) {
        return `${greeting}, ${name}!`;
    };
}

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Filter even numbers and double them
const result = numbers
    .filter(num => num % 2 === 0)
    .map(num => num * 2)
    .reduce((sum, num) => sum + num, 0);

console.log(calculateArea(5, 3)); // 15
console.log(calculatePerimeter(5, 3)); // 16

const helloGreeter = createGreeter("Hello");
console.log(helloGreeter("Alice")); // "Hello, Alice!"

console.log(result); // 60 (2+4+6+8+10) * 2
```

```swift !! swift
// Swift exercise
func calculateArea(width: Int, height: Int) -> Int {
    return width * height
}

let calculatePerimeter: (Int, Int) -> Int = { width, height in
    2 * (width + height)
}

func createGreeter(greeting: String) -> (String) -> String {
    return { name in
        "\(greeting), \(name)!"
    }
}

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// Filter even numbers and double them
let result = numbers
    .filter { $0 % 2 == 0 }
    .map { $0 * 2 }
    .reduce(0, +)

print(calculateArea(width: 5, height: 3)) // 15
print(calculatePerimeter(5, 3)) // 16

let helloGreeter = createGreeter(greeting: "Hello")
print(helloGreeter("Alice")) // "Hello, Alice!"

print(result) // 60 (2+4+6+8+10) * 2
```
</UniversalEditor>

### Exercise 2: Advanced Closure Usage

<UniversalEditor title="Exercise 2: Advanced Closure Usage" compare={true}>
```javascript !! js
// JavaScript advanced closure exercise
function createCounter(initialValue = 0) {
    let count = initialValue;
    
    return {
        increment: () => ++count,
        decrement: () => --count,
        reset: () => { count = initialValue; return count; },
        getValue: () => count
    };
}

function memoize(fn) {
    const cache = new Map();
    
    return function(...args) {
        const key = JSON.stringify(args);
        if (cache.has(key)) {
            return cache.get(key);
        }
        const result = fn.apply(this, args);
        cache.set(key, result);
        return result;
    };
}

const expensiveFunction = memoize((n) => {
    console.log(`Computing for ${n}`);
    return n * n;
});

const counter = createCounter(10);
console.log(counter.getValue()); // 10
console.log(counter.increment()); // 11
console.log(counter.increment()); // 12
console.log(counter.reset()); // 10

console.log(expensiveFunction(5)); // Computing for 5, 25
console.log(expensiveFunction(5)); // 25 (cached)
```

```swift !! swift
// Swift advanced closure exercise
func createCounter(initialValue: Int = 0) -> (increment: () -> Int, decrement: () -> Int, reset: () -> Int, getValue: () -> Int) {
    var count = initialValue
    
    let increment = { [count] in
        count += 1
        return count
    }
    
    let decrement = { [count] in
        count -= 1
        return count
    }
    
    let reset = { [initialValue] in
        count = initialValue
        return count
    }
    
    let getValue = { count }
    
    return (increment: increment, decrement: decrement, reset: reset, getValue: getValue)
}

func memoize<T: Hashable, U>(_ fn: @escaping (T) -> U) -> (T) -> U {
    var cache: [T: U] = [:]
    
    return { input in
        if let cached = cache[input] {
            return cached
        }
        let result = fn(input)
        cache[input] = result
        return result
    }
}

let expensiveFunction = memoize { (n: Int) -> Int in
    print("Computing for \(n)")
    return n * n
}

let counter = createCounter(initialValue: 10)
print(counter.getValue()) // 10
print(counter.increment()) // 11
print(counter.increment()) // 12
print(counter.reset()) // 10

print(expensiveFunction(5)) // Computing for 5, 25
print(expensiveFunction(5)) // 25 (cached)
```
</UniversalEditor>

## 8. Key Takeaways

### 8.1 Function and Closure Differences

| Feature | JavaScript | Swift | Key Difference |
|---|---|---|---|
| **Function Declaration** | `function` keyword or arrow functions | `func` keyword | Swift requires explicit types |
| **Parameter Types** | Dynamic typing | Static typing | Swift provides compile-time safety |
| **Return Types** | Inferred | Explicit | Swift requires return type declaration |
| **Closure Syntax** | Arrow functions `=>` | `{ } in` syntax | Swift has more flexible syntax options |
| **Capture Lists** | Lexical scoping | Explicit capture lists | Swift provides more control over memory |
| **Higher-Order Functions** | Array methods | Collection methods | Similar functionality, different syntax |

### 8.2 Best Practices

1. **Use Type Annotations**: Explicit types make code clearer and safer
2. **Prefer Trailing Closures**: Use trailing closure syntax for better readability
3. **Use Capture Lists**: Explicitly control closure capture to prevent retain cycles
4. **Leverage Type Inference**: Let Swift infer types when obvious
5. **Use Functional Patterns**: Take advantage of Swift's functional programming features
6. **Handle Memory Management**: Use weak and unowned references appropriately

### 8.3 Common Pitfalls

1. **Forgetting Parameter Labels**: Swift uses external parameter names
2. **Ignoring Return Types**: Swift requires explicit return type declarations
3. **Retain Cycles**: Not using weak references in closures that capture self
4. **Type Mismatches**: Not matching closure types with expected function types
5. **Over-complicating Closures**: Using full syntax when shorthand is clearer

## 9. Next Steps

In the next module, we'll explore collections in Swift, including:
- Arrays, dictionaries, and sets
- Collection methods and operations
- Custom collection types
- Performance considerations

This foundation in functions and closures will prepare you for more advanced Swift programming concepts and iOS development. 